/*
PilaList.java
Autor: Paola Garcia, carnet 10205
Fecha: 20 agosto 2011
Descripcion: clase pilaList, que implemente a la interfaz
se encarga de realizar las operaciones. 
*/

import java.util.ArrayList;
import java.util.List;

public class PilaList<T> implements InterfazList<T>{
	
	//Creacion del stack
	
	private List<T> stack = new ArrayList<T>();
	
	//Declaracion de variables

	protected T data; 
	protected PilaList<T> nextElement; 
	protected int count; 
	protected PilaList<T> head; 
	
	
	public PilaList(T v, PilaList<T> next){
		data = v;
		nextElement = next;
	}
	
	public PilaList(T v){
		this(v,null);
	}
	
	public PilaList<T> next(){
		return nextElement;
	}
	
	public void setNext(PilaList<T> next){
		nextElement = next;
	}
	
	public T value(){
		return data;
	}
	
	public void setValue(T value){
		data = value;
	}
	
	public SinglyLinkedList(){
		head = null;
		count = 0;
	}
	
	public int size(){
		int elementCount = 0;
		PilaList<T> finger = head;
		while (finger != null) {
			elementCount++;
			finger = finger.next();
		}
		return elementCount;
	}
	
	public void addFirst(T value){
		head = new PilaList<T>(value, head);
		count++;
	}
	
	public T removeFirst(){
		PilaList<T> temp = head;
		head = head.next(); 
		count--;
		return temp.value();
	}
	
	public T getFirst(){
		return head.value();
	}
	
	public void addLast(T value){
		PilaList<T> temp = new PilaList<T>(value,null);
		if (head != null){
			PilaList<T> finger = head;
			while (finger.next() != null){
				finger = finger.next();
			}
			finger.setNext(temp);
		} else head = temp;
		count++;
	}
	
	public T removeLast(){
		PilaList<T> finger = head;
		PilaList<T> previous = null;
		Assert.pre(head != null,"Lista no vacia.");
		while (finger.next() != null){
			previous = finger;
			finger = finger.next();
		}
		if (previous == null){
			head = null;
		}
		else{
			previous.setNext(null);
		}
		count--;
		return finger.value();
	}
	
	public boolean contains(T value){
		PilaList<T> finger = head;
		while (finger != null && !finger.value().equals(value)){
			finger = finger.next();
		}
		return finger != null;
	}

	public T remove(T value){
		PilaList<T> finger = head;
		PilaList<T> previous = null;
		while (finger != null && !finger.value().equals(value)){
			previous = finger;
			finger = finger.next();
		}
		if (finger != null) {
			if (previous == null){
				head = finger.next();
			} 
			else { 
				previous.setNext(finger.next());
			}
			count--;
			return finger.value();
		}
		return null;
	}
	
	public void clear(){
		head = null;
		count = 0;
	}
	
	public void add(int i, T o){
		Assert.pre((0 <= i) && (i <= size()), "Index in range.");
		if (i == size()) {
			addLast(o);
		} 
		else if (i == 0) {
			addFirst(o);
		} 
		else {
			PilaList<T> previous = null;
			PilaList<T> finger = head;
			while (i > 0){
				previous = finger;
				finger = finger.next();
				i--;
			}
		PilaList<T> current = new PilaLista<T>(o,finger);
		count++;
		previous.setNext(current);
		}
	}
	
	public T remove(int i){
		Assert.pre((0 <= i) && (i < size()), "Index in range.");
		if (i == 0) 
			return removeFirst();
		else 
			if (i == size()-1) return removeLast();
				PilaList<T> previous = null;
				PilaList<T> finger = head;
				while (i > 0){
					previous = finger;
					finger = finger.next();
					i--;
				}
			previous.setNext(finger.next());
			count--;
			return finger.value();
	}
	
	//Metodo para dividir dos numeros
	public double div(double uno, double dos){
		resp = uno / dos;
		return resp;	
	}
	
	
	//Metodo para multiplicar dos numeros
	public double mul(double uno, double dos){
		resp = uno * dos;
		return resp;	
	}
	
	//Metodo para restar dos numeros
	public double rest(double uno, double dos){
		resp = uno - dos;
		return resp;	
	}

	//Metodo para sumar dos numeros
	public double sum(double uno, double dos){
		resp = uno + dos;
		return resp;
		
	}
}